package com.cqupt.utils;


import com.google.gson.Gson;
import okhttp3.HttpUrl;
import org.java_websocket.WebSocket;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

public class TtsUtil {


    // 地址与鉴权信息
    private static final String hostUrl = "https://tts-api.xfyun.cn/v2/tts";
    // 均到控制台-语音合成页面获取

    // 均到控制台-语音合成页面获取
    private static final String appid = "a830a3cb";
    private static final String apiSecret = "OWQzNmFkN2U3NmFmMjE5NTAyOTU4MTNl";
    private static final String apiKey = "6a73cfa8e86bde2f546004fcdff19224";

    // json
    private static final Gson gson = new Gson();
    private static boolean wsCloseFlag = false;

    public static byte[] tts(String text) throws Exception {
        String wsUrl = getAuthUrl(hostUrl, apiKey, apiSecret).replace("https://", "wss://");
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        websocketWork(wsUrl, outputStream, text);
        try (FileOutputStream fileOutputStream = new FileOutputStream("./audio" + ".mp3")) {
            outputStream.writeTo(fileOutputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }

//        return Base64.getEncoder().encodeToString(outputStream.toByteArray());
        return outputStream.toByteArray();
    }

    // Websocket方法
    private static void websocketWork(String wsUrl, ByteArrayOutputStream outputStream, String text) {
        try {
            URI uri = new URI(wsUrl);
            WebSocketClient webSocketClient = new WebSocketClient(uri) {
                @Override
                public void onOpen(ServerHandshake serverHandshake) {
                    System.out.println("ws建立连接成功...");
                }

                @Override
                public void onMessage(String message) {
                    JsonParse myJsonParse = gson.fromJson(message, JsonParse.class);
                    if (myJsonParse.code != 0) {
                        System.out.println("发生错误，错误码为：" + myJsonParse.code);
                        System.out.println("本次请求的sid为：" + myJsonParse.sid);
                    }
                    if (myJsonParse.data != null) {
                        try {
                            byte[] audioData = Base64.getDecoder().decode(myJsonParse.data.audio);
                            outputStream.write(audioData);
                            outputStream.flush();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        if (myJsonParse.data.status == 2) {
                            try {
                                outputStream.close();
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                            System.out.println("本次请求的sid==>" + myJsonParse.sid);
                            System.out.println("合成成功，音频数据已获取");
                            wsCloseFlag = true;
                        }
                    }
                }

                @Override
                public void onClose(int i, String s, boolean b) {
                    System.out.println("ws链接已关闭，本次请求完成...");
                    wsCloseFlag = false;
                }

                @Override
                public void onError(Exception e) {
                    System.out.println("发生错误 " + e.getMessage());
                }
            };
            webSocketClient.connect();
            while (!webSocketClient.getReadyState().equals(WebSocket.READYSTATE.OPEN)) {
                Thread.sleep(100);
            }
            MyThread webSocketThread = new MyThread(webSocketClient, text);
            webSocketThread.start();
            while (!wsCloseFlag) {
                Thread.sleep(200);
            }
            webSocketClient.close();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

    // 线程来发送音频与参数
    static class MyThread extends Thread {
        WebSocketClient webSocketClient;
        String text;

        public MyThread(WebSocketClient webSocketClient, String text) {
            this.webSocketClient = webSocketClient;
            this.text = text;
        }

        public void run() {
            String requestJson;
            try {
                requestJson = "{\n" +
                        "  \"common\": {\n" +
                        "    \"app_id\": \"" + appid + "\"\n" +
                        "  },\n" +
                        "  \"business\": {\n" +
                        "    \"aue\": \"lame\",\n" +
                        "    \"tte\": \"UTF8\",\n" +
                        "    \"ent\": \"intp65_en\",\n" +
//                        "    \"vcn\": \"x4_EnUs_Lindsay_assist\",\n" +
//                        "    \"vcn\": \"x4_enus_lucy_education\",\n" +
                        "    \"vcn\": \"x4_enus_catherine_profnews\",\n" +
                        "    \"reg\": \"0\",\n" +
                        "    \"pitch\": 50,\n" +
                        "    \"speed\": 50\n" +
                        "  },\n" +
                        "  \"data\": {\n" +
                        "    \"status\": 2,\n" +
                        "    \"text\": \"" + Base64.getEncoder().encodeToString(text.getBytes(StandardCharsets.UTF_8)) + "\"\n" +
                        "  }\n" +
                        "}";
                webSocketClient.send(requestJson);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    // 鉴权方法
    private static String getAuthUrl(String hostUrl, String apiKey, String apiSecret) throws Exception {
        URL url = new URL(hostUrl);
        SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        format.setTimeZone(TimeZone.getTimeZone("GMT"));
        String date = format.format(new Date());

        String preStr = "host: " + url.getHost() + "\n" +
                "date: " + date + "\n" +
                "GET " + url.getPath() + " HTTP/1.1";

        Mac mac = Mac.getInstance("hmacsha256");
        SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "hmacsha256");
        mac.init(spec);
        byte[] hexDigits = mac.doFinal(preStr.getBytes(StandardCharsets.UTF_8));

        String sha = Base64.getEncoder().encodeToString(hexDigits);
        String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"",
                apiKey, "hmac-sha256", "host date request-line", sha);

        HttpUrl httpUrl = Objects.requireNonNull(HttpUrl.parse("https://" + url.getHost() + url.getPath())).newBuilder()
                .addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorization.getBytes(StandardCharsets.UTF_8)))
                .addQueryParameter("date", date)
                .addQueryParameter("host", url.getHost())
                .build();

        return httpUrl.toString();
    }

    // 返回的json结果拆解
    static class JsonParse {
        int code;
        String sid;
        Data data;
    }

    static class Data {
        int status;
        String audio;
    }
}